﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using StairsModuleAndEdit.StairsEdit.Common;
using StairsModuleAndEdit.StairsEdit.DataDefine;

namespace StairsModuleAndEdit.StairsEdit.Managers
{
	internal class SplitingAllStairs
	{
		public SplitingAllStairs(Document docVal, List<Stairs> stairsVal)
		{
			this.m_doc = docVal;
			this.arStairs = stairsVal;
		}

		public bool DealStairs(ref IList<Stairs> lstRawstairs, ref string message)
		{
			if (this.arStairs.LongCount<Stairs>() < 1L)
			{
				return true;
			}
			foreach (Element element in this.arStairs)
			{
				Stairs stairs = element as Stairs;
				stairs.GetTypeId();
				ElementId typeId = stairs.GetTypeId();
				StairsType stairsType = this.m_doc.GetElement(typeId) as StairsType;
				StairsRunType stairsRunType = this.m_doc.GetElement(stairsType.RunType) as StairsRunType;
				this.m_ThreadThick = stairsRunType.TreadThickness;
				this.m_RiseThick = stairsRunType.RiserThickness;
				this.m_StructThick = stairsRunType.StructuralDepth;
				if (this.m_ThreadThick < CommonUnit._epsDouble || this.m_RiseThick < CommonUnit._epsDouble || this.m_StructThick < CommonUnit._epsDouble)
				{
					lstRawstairs.Add(stairs);
				}
				else
				{
					XYZ xyz = new XYZ(0.0, 0.0, 1.0);
					Stairs stairs2 = null;
					Transaction transaction = new Transaction(this.m_doc, "split");
					transaction.Start();
					try
					{
						ICollection<ElementId> collection = ElementTransformUtils.CopyElement(this.m_doc, stairs.Id, xyz);
						IEnumerator<ElementId> enumerator2 = collection.GetEnumerator();
						enumerator2.MoveNext();
						stairs2 = (this.m_doc.GetElement(enumerator2.Current) as Stairs);
						this.splitStairs(stairs, 0);
						this.splitStairs(stairs2, 1);
						StairsXDataManager.WriteArchStairsId(stairs2, stairs.Id);
						transaction.Commit();
					}
					catch (Exception ex)
					{
						message = ex.Message;
						transaction.RollBack();
						return false;
					}
					if (!stairs2.IsValidObject)
					{
						return false;
					}
					if (!this.AdjustStairs(stairs2, ref message))
					{
						return false;
					}
					this.DeleteRailing(stairs2);
				}
			}
			return true;
		}

		private Result DeleteRailing(Stairs stairNew)
		{
			Transaction transaction = new Transaction(this.m_doc, "Delete Railing");
			transaction.Start();
			ICollection<ElementId> associatedRailings = stairNew.GetAssociatedRailings();
			foreach (ElementId elementId in associatedRailings)
			{
				this.m_doc.Delete(elementId);
			}
			transaction.Commit();
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		private void splitStairs(Stairs stairNew, int iflg)
		{
			int num = stairNew.get_Parameter(BuiltInParameter.STAIRS_DESIRED_NUMBER_OF_RISERS).AsInteger();
			ElementId typeId = stairNew.GetTypeId();
			StairsType stairsType = this.m_doc.GetElement(typeId) as StairsType;
			string text = stairsType.Name + "-面层";
			if (iflg == 1)
			{
				text = stairsType.Name + "-结构层";
			}
			CommonUnit.CorrectYJKStairsTypeByNumber(this.m_doc, ref text);
			StairsType stairsType2 = null;
			bool flag = true;
			CommonUnit.GetElementType<StairsType>(this.m_doc, text, ref stairsType2, ref flag);
			stairsType2 = (stairsType.Duplicate(text) as StairsType);
			if (iflg == 0)
			{
				stairsType2.GetParameter(BuiltInParameter.STAIRSTYPE_HAS_INTERMEDIATE_SUPPORT).Set(0);
				stairsType2.GetParameter(BuiltInParameter.STAIRSTYPE_HAS_LEFT_SUPPORT).Set(0);
				stairsType2.GetParameter(BuiltInParameter.STAIRSTYPE_HAS_RIGHT_SUPPORT).Set(0);
			}
			stairsType2.MaxRiserHeight = stairNew.ActualRiserHeight;
			StairsRunType runTypeold = this.m_doc.GetElement(stairsType2.RunType) as StairsRunType;
			StairsRunType stairsRunType = this.GetStairsRunType(iflg, runTypeold);
			StairsLandingType landingTypeold = this.m_doc.GetElement(stairsType2.LandingType) as StairsLandingType;
			StairsLandingType stairsLandingType = this.GetStairsLandingType(iflg, stairsRunType, landingTypeold);
			stairsType2.RunType = stairsRunType.Id;
			stairsType2.LandingType = stairsLandingType.Id;
			stairNew.ChangeTypeId(stairsType2.Id);
			this.m_landingType = stairsLandingType;
			stairNew.get_Parameter(BuiltInParameter.STAIRS_DESIRED_NUMBER_OF_RISERS).Set(num);
		}

		private void GetStairsRunTypeName(int iflg, ref string strRuntypeName)
		{
			if (iflg == 1)
			{
				strRuntypeName = (this.m_StructThick * CommonUnit.MM2Feet).ToString("f1");
				strRuntypeName += "mm楼梯板厚 0mm踢面厚 0mm踏板厚";
				return;
			}
			string text = (this.m_RiseThick * CommonUnit.MM2Feet).ToString("f1");
			text += "mm踢面厚";
			string text2 = (this.m_ThreadThick * CommonUnit.MM2Feet).ToString("f1");
			text2 += "mm踏板厚";
			strRuntypeName = "0mm楼梯板厚 " + text2 + " " + text;
		}

		private StairsRunType GetStairsRunType(int iflg, StairsRunType runTypeold)
		{
			string text = null;
			this.GetStairsRunTypeName(iflg, ref text);
			StairsRunType stairsRunType = null;
			bool flag = false;
			CommonUnit.GetElementType<StairsRunType>(this.m_doc, text, ref stairsRunType, ref flag);
			if (flag)
			{
				stairsRunType = (runTypeold.Duplicate(text) as StairsRunType);
				if (iflg == 0)
				{
					stairsRunType.StructuralDepth = 0.0;
					stairsRunType.GetParameter(BuiltInParameter.STAIRS_TRISERTYPE_TREAD).Set(1);
					stairsRunType.GetParameter(BuiltInParameter.STAIRS_TRISERTYPE_RISER).Set(1);
					stairsRunType.GetParameter(BuiltInParameter.STAIRS_RUNTYPE_UNDERSIDE_SURFACE_TYPE).Set(0);
				}
				else
				{
					stairsRunType.GetParameter(BuiltInParameter.STAIRS_TRISERTYPE_TREAD).Set(0);
					stairsRunType.GetParameter(BuiltInParameter.STAIRS_TRISERTYPE_RISER).Set(0);
					stairsRunType.GetParameter(BuiltInParameter.STAIRS_RUNTYPE_UNDERSIDE_SURFACE_TYPE).Set(1);
				}
			}
			if (iflg == 0)
			{
				Parameter parameter = stairsRunType.GetParameter(BuiltInParameter.STAIRS_RUNTYPE_RUN_MATERIAL);
				if (parameter != null && !parameter.IsReadOnly)
				{
					Parameter parameter2 = stairsRunType.GetParameter(BuiltInParameter.STAIRS_TRISERTYPE_TREAD_MATERIAL);
					if (parameter2 != null)
					{
						ElementId elementId = parameter2.AsElementId();
						if (elementId != null && elementId.IntegerValue != -1)
						{
							parameter.Set(elementId);
						}
					}
				}
			}
			return stairsRunType;
		}

		private void GetStairsLandingTypeName(int iflg, double dThickness, ref string strLandTypeName)
		{
			if (iflg == 1)
			{
				strLandTypeName += dThickness.ToString("f1");
				strLandTypeName += "mm休息板厚";
				return;
			}
			strLandTypeName = "0mm休息板厚0mm踏板厚度";
		}

		private StairsLandingType GetStairsLandingType(int iflg, StairsRunType runTypeNew, StairsLandingType landingTypeold)
		{
			string text = "";
			double dThickness = landingTypeold.Thickness * CommonUnit.MM2Feet;
			this.GetStairsLandingTypeName(iflg, dThickness, ref text);
			StairsLandingType stairsLandingType = null;
			bool flag = false;
			CommonUnit.GetElementType<StairsLandingType>(this.m_doc, text, ref stairsLandingType, ref flag);
			if (flag)
			{
				stairsLandingType = (landingTypeold.Duplicate(text) as StairsLandingType);
				if (iflg == 0)
				{
					stairsLandingType.GetParameter(BuiltInParameter.STAIRS_LANDINGTYPE_USE_SAME_TRISER_AS_RUN).Set(1);
					stairsLandingType.GetParameter(BuiltInParameter.STAIRS_LANDINGTYPE_THICKNESS).Set(0.00032808398950131233);
				}
				else
				{
					stairsLandingType.GetParameter(BuiltInParameter.STAIRS_LANDINGTYPE_USE_SAME_TRISER_AS_RUN).Set(1);
				}
			}
			if (iflg == 0)
			{
				Parameter parameter = stairsLandingType.GetParameter(BuiltInParameter.STAIRS_LANDINGTYPE_LANDING_MATERIAL);
				if (parameter != null && !parameter.IsReadOnly)
				{
					Parameter parameter2 = runTypeNew.GetParameter(BuiltInParameter.STAIRS_TRISERTYPE_TREAD_MATERIAL);
					if (parameter2 != null)
					{
						ElementId elementId = parameter2.AsElementId();
						if (elementId != null && elementId.IntegerValue != -1)
						{
							parameter.Set(elementId);
						}
					}
				}
			}
			return stairsLandingType;
		}

		private bool AdjustStairs(Stairs stair, ref string strMessage)
		{
			StairsEditScope stairsEditScope = new StairsEditScope(this.m_doc, "修改楼梯");
			stairsEditScope.Start(stair.Id);
			Transaction transaction = new Transaction(this.m_doc, "将梯段休息平台分开处理");
			transaction.Start();
			try
			{
				List<LandingInfo> landingInfos = new List<LandingInfo>();
				this.DeleteAllLanding(stair, ref landingInfos, ref strMessage);
				List<runinfo> runboundLoops = new List<runinfo>();
				this.moveRuns(stair, ref runboundLoops);
				this.DrawLandings(ref stair, landingInfos, runboundLoops);
				Parameter parameter = stair.GetParameter(BuiltInParameter.STAIRS_BASE_OFFSET);
				parameter.Set(parameter.AsDouble() - this.m_ThreadThick);
				parameter = stair.GetParameter(BuiltInParameter.STAIRS_TOP_OFFSET);
				if (!parameter.IsReadOnly)
				{
					parameter.Set(parameter.AsDouble() - this.m_ThreadThick);
				}
				transaction.Commit();
				stairsEditScope.Commit(new StairsEditScopeFailuresPreprocessor());
			}
			catch (Exception ex)
			{
				strMessage = ex.Message;
				transaction.RollBack();
				stairsEditScope.Cancel();
				return false;
			}
			return true;
		}

		private bool DrawLandings(ref Stairs stair, List<LandingInfo> landingInfos, List<runinfo> RunboundLoops)
		{
			foreach (runinfo runinfo in RunboundLoops)
			{
				int num = 0;
				int num2 = 0;
				while ((long)num2 < landingInfos.LongCount<LandingInfo>())
				{
					num = 0;
					LandingInfo value = landingInfos[num2];
					if (value.ids.IndexOf(runinfo.runid) != -1)
					{
						IList<Curve> runRiseCurves = runinfo.runRiseCurves;
						IList<Curve> list = new List<Curve>();
						List<Curve> list2 = new List<Curve>(value.curves);
						int i = 0;
						while ((long)i < list2.LongCount<Curve>())
						{
							Curve curve = list2[i];
							if (curve is Arc)
							{
								list.Add(curve);
							}
							else
							{
								XYZ xyz = null;
								Curve curve2;
								if (i > 0)
								{
									curve2 = list2[i - 1];
									if (curve2 is Line)
									{
										xyz = (curve2 as Line).Direction;
									}
								}
								else
								{
									curve2 = list2[(int)list2.LongCount<Curve>() - 1];
									if (curve2 is Line)
									{
										xyz = (curve2 as Line).Direction;
									}
								}
								int num3 = (i + 1) % (int)list2.LongCount<Curve>();
								XYZ xyz2 = null;
								if (list2[num3] is Line)
								{
									xyz2 = (list2[num3] as Line).Direction;
								}
								XYZ xyz3 = (curve as Line).Direction.Normalize();
								Line line = curve as Line;
								line.GetEndPoint(0);
								XYZ endPoint = line.GetEndPoint(1);
								XYZ xyz4 = (runRiseCurves[0] as Line).Direction.Normalize();
								if (xyz3.IsAlmostEqualTo(xyz4) || xyz3.IsAlmostEqualTo(xyz4.Negate()))
								{
									foreach (Curve curve3 in runRiseCurves)
									{
										XYZ endPoint2 = curve3.GetEndPoint(0);
										XYZ endPoint3 = curve3.GetEndPoint(1);
										XYZ xyz5 = endPoint3 - endPoint2;
										XYZ xyz6 = endPoint2 + xyz5 / 2.0;
										double num4 = line.Distance(xyz6);
										if (Math.Abs(num4 - this.m_RiseThick) < CommonUnit._epsDouble)
										{
											num = 1;
											if (xyz3.IsAlmostEqualTo((curve3 as Line).Direction.Normalize()))
											{
												if (xyz.IsAlmostEqualTo((curve3 as Line).Direction.Normalize()))
												{
													if (i == 0)
													{
														list.Add(curve2);
													}
													list.Add(Line.CreateBound(curve2.GetEndPoint(1), endPoint2));
												}
												else if (i == 0)
												{
													list.Add(Line.CreateBound(curve2.GetEndPoint(0), endPoint2));
												}
												else
												{
													list[i - 1] = Line.CreateBound(curve2.GetEndPoint(0), endPoint2);
												}
												list.Add(curve3);
												if (xyz2.IsAlmostEqualTo((curve3 as Line).Direction.Normalize()))
												{
													list.Add(Line.CreateBound(endPoint3, endPoint));
												}
												else if (num3 == 0)
												{
													list[num3] = Line.CreateBound(endPoint3, list2[num3].GetEndPoint(1));
												}
												else
												{
													list.Add(Line.CreateBound(endPoint3, list2[num3].GetEndPoint(1)));
												}
											}
											else
											{
												if (xyz.IsAlmostEqualTo((curve3 as Line).Direction.Normalize().Negate()))
												{
													if (i == 0)
													{
														list.Add(curve2);
													}
													list.Add(Line.CreateBound(curve2.GetEndPoint(1), endPoint3));
												}
												else if (i == 0)
												{
													list.Add(Line.CreateBound(curve2.GetEndPoint(0), endPoint3));
												}
												else
												{
													list[i - 1] = Line.CreateBound(curve2.GetEndPoint(0), endPoint3);
												}
												list.Add(Line.CreateBound(endPoint3, endPoint2));
												if (xyz2.IsAlmostEqualTo((curve3 as Line).Direction.Normalize().Negate()))
												{
													list.Add(Line.CreateBound(endPoint2, endPoint));
													if ((long)i < list2.LongCount<Curve>() - 1L)
													{
														list.Add(list2[num3]);
													}
												}
												else if (num3 == 0)
												{
													list[num3] = Line.CreateBound(endPoint2, list2[num3].GetEndPoint(1));
												}
												else
												{
													list.Add(Line.CreateBound(endPoint2, list2[num3].GetEndPoint(1)));
												}
											}
											int num5 = (int)list2.LongCount<Curve>();
											if (i == 0)
											{
												num5--;
											}
											for (i += 2; i < num5; i++)
											{
												list.Add(list2[i]);
											}
											break;
										}
									}
									if (num == 0)
									{
										list.Add(line);
									}
								}
								else
								{
									list.Add(line);
								}
								if (num == 1)
								{
									value.curves = list;
									landingInfos[num2] = value;
									break;
								}
							}
							i++;
						}
					}
					num2++;
				}
			}
			foreach (LandingInfo landingInfo in landingInfos)
			{
				CurveLoop curveLoop = CurveLoop.Create(landingInfo.curves);
				double baseElevation = landingInfo.BaseElevation;
				StairsLanding.CreateSketchedLanding(this.m_doc, stair.Id, curveLoop, baseElevation);
			}
			return true;
		}

		private bool moveRuns(Stairs stair, ref List<runinfo> boundLoops)
		{
			ICollection<ElementId> stairsRuns = stair.GetStairsRuns();
			IEnumerator<ElementId> enumerator = stairsRuns.GetEnumerator();
			while (enumerator.MoveNext())
			{
				SubTransaction subTransaction = new SubTransaction(this.m_doc);
				subTransaction.Start();
				ElementId elementId = enumerator.Current;
				StairsRun stairsRun = this.m_doc.GetElement(elementId) as StairsRun;
				CurveLoop curveLoop = stairsRun.GetStairsPath();
				XYZ xyz = XYZ.Zero;
				CurveLoopIterator curveLoopIterator = curveLoop.GetCurveLoopIterator();
				if (curveLoopIterator.MoveNext())
				{
					Curve curve = curveLoopIterator.Current;
					if (curve is Line)
					{
						Line line = curve as Line;
						XYZ origin = line.Origin;
						xyz = line.Direction;
						ElementTransformUtils.MoveElement(this.m_doc, stairsRun.Id, xyz * this.m_RiseThick);
					}
					else
					{
						Arc arc = curve as Arc;
						double radius = arc.Radius;
						curveLoop = stairsRun.GetFootprintBoundary();
						IEnumerator<Curve> enumerator2 = curveLoop.GetEnumerator();
						while (enumerator2.MoveNext())
						{
							if (enumerator2.Current is Arc)
							{
								Arc arc2 = enumerator2.Current as Arc;
								if (arc2.Radius > radius)
								{
									radius = arc2.Radius;
									break;
								}
							}
						}
						XYZ center = arc.Center;
						double num = Math.PI*2 * radius;
						double num2 = this.m_RiseThick / num * 2.0 * Math.PI;
						Line line2 = Line.CreateUnbound(center, arc.Normal);
						ElementTransformUtils.RotateElement(this.m_doc, stairsRun.Id, line2, num2);
					}
					subTransaction.Commit();
					curveLoop = stairsRun.GetFootprintBoundary();
					List<Curve> list = new List<Curve>();
					IEnumerator<Curve> enumerator3 = curveLoop.GetEnumerator();
					while (enumerator3.MoveNext() && enumerator3.Current is Line)
					{
						XYZ xyz2 = (enumerator3.Current as Line).Direction.Normalize();
						if (!xyz2.IsAlmostEqualTo(xyz.Normalize()) && !xyz2.Negate().IsAlmostEqualTo(xyz.Normalize()))
						{
							list.Add(enumerator3.Current);
						}
					}
					runinfo item = new runinfo(stairsRun.Id, list);
					boundLoops.Add(item);
				}
			}
			return true;
		}

		private bool DeleteAllLanding(Stairs stair, ref List<LandingInfo> landingsCurveloop, ref string strMessage)
		{
			try
			{
				ICollection<ElementId> stairsLandings = stair.GetStairsLandings();
				foreach (ElementId elementId in stairsLandings)
				{
					StairsLanding stairsLanding = this.m_doc.GetElement(elementId) as StairsLanding;
					List<ElementId> list = new List<ElementId>();
					IList<StairsComponentConnection> connections = stairsLanding.GetConnections();
					foreach (StairsComponentConnection stairsComponentConnection in connections)
					{
						Element element = this.m_doc.GetElement(stairsComponentConnection.PeerElementId);
						if (element is StairsRun)
						{
							list.Add(stairsComponentConnection.PeerElementId);
						}
					}
					this.m_landingType = (this.m_doc.GetElement(stairsLanding.GetTypeId()) as StairsLandingType);
					CurveLoop footprintBoundary = stairsLanding.GetFootprintBoundary();
					foreach (Curve curve in footprintBoundary)
					{
					}
					double baseElevation = stairsLanding.BaseElevation;
					LandingInfo item = new LandingInfo(baseElevation, footprintBoundary, list);
					landingsCurveloop.Add(item);
					this.m_doc.Delete(elementId);
				}
			}
			catch (Exception ex)
			{
				strMessage = ex.Message;
				return false;
			}
			return true;
		}

		private Document m_doc;

		private List<Stairs> arStairs;

		private double m_RiseThick;

		private double m_ThreadThick;

		private double m_StructThick;

		private StairsLandingType m_landingType;
	}
}
